#include "../include/Canvas.h"
#include "../base.h"

#define LOG_TAG "Canvas"

static jclass getClass(JNIEnv* env,const char * className)
{
	return (*env)->FindClass(env,className);
}

static jclass getCanvasClass(JNIEnv* env)
{
	return getClass(env,"android/graphics/Canvas");
}

//通过位图，创建画布
Canvas newCanvas(Bitmap bitmap)
{
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID( env,clazz,"<init>","(Landroid/graphics/Bitmap;)V" );
	jobject obj = (*env)->NewObject(env,clazz,methoID,bitmap);
	Canvas canvas = (*env)->NewGlobalRef(env,obj);
	(*env)->DeleteLocalRef(env,obj);
	(*env)->DeleteLocalRef(env,clazz);
	return canvas;
}

//删除画布对象
void deleteCanvas(Canvas thiz)
{
	if(thiz==NULL)
	{
		LOGE("deleteCanvas thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	(*env)->DeleteGlobalRef(env,thiz);
}

//使用指定颜色清屏
void Canvas_drawColor(Canvas thiz,int color)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawColor thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawColor","(I)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,color);
}

//画点
void Canvas_drawPoint(Canvas thiz,float x,float y,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawPoint thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawPoint","(FFLandroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,x,y,paint);
}

//画线
void Canvas_drawLine(Canvas thiz,float startX,float startY,float stopX,float stopY,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawLine thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawLine","(FFFFLandroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,startX,startY,stopX,stopY,paint);
}

//画文本
void Canvas_drawText(Canvas thiz,const char * text,float x,float y,Paint paint)
{
	jstring str = createJString(text);
	Canvas_drawJString(thiz,str,x,y,paint);
	deleteJString(str);
}

//画文本
void Canvas_drawJString(Canvas thiz,jstring string,float x,float y,Paint paint)
{
	Canvas_drawJStringEx(thiz,string,0,lengthOfJString(string),x,y,paint);
}

//画文本
void Canvas_drawJStringEx(Canvas thiz,jstring string,int start,int end,float x,float y,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawJStringEx thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawText","(Ljava/lang/String;IIFFLandroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,string,start,end,x,y-Paint_getDescent(paint),paint);
}

//画矩形
void Canvas_drawRect(Canvas thiz,float left, float top, float right, float bottom,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawRect thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawRect","(FFFFLandroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,left,top,right,bottom,paint);
}

//画矩形
void Canvas_drawRectEx(Canvas thiz,RectF rect,Paint paint)
{
	Canvas_drawRect(thiz,rect.left,rect.top,rect.right,rect.buttom,paint);
}

static jobject newJRectF(JNIEnv* env,float left,float top,float right,float buttom){
	const char *className = "android/graphics/RectF";
	jclass clazz = getClass(env,className);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID( env,clazz,"<init>","(FFFF)V" );
	jobject obj = (*env)->NewObject(env,clazz,methoID,left,top,right,buttom);
	jobject rectF = (*env)->NewGlobalRef(env,obj);
	(*env)->DeleteLocalRef(env,obj);
	(*env)->DeleteLocalRef(env,clazz);
	return rectF;
}

static void deleteJRectF(JNIEnv* env,jobject thiz){
	(*env)->DeleteGlobalRef(env,thiz);
}

static jobject newJRect(JNIEnv* env,int left,int top,int right,int buttom){
	const char *className = "android/graphics/Rect";
	jclass clazz = getClass(env,className);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID( env,clazz,"<init>","(IIII)V" );
	jobject obj = (*env)->NewObject(env,clazz,methoID,left,top,right,buttom);
	jobject rectF = (*env)->NewGlobalRef(env,obj);
	(*env)->DeleteLocalRef(env,obj);
	(*env)->DeleteLocalRef(env,clazz);
	return rectF;
}

static void deleteJRect(JNIEnv* env,jobject thiz){
	(*env)->DeleteGlobalRef(env,thiz);
}

//画圆角矩形
void Canvas_drawRoundRect(Canvas thiz,float left, float top, float right, float bottom,float rx,float ry,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawRect thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	jobject rectF = newJRectF(env,left,top,right,bottom);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawRoundRect","(Landroid/graphics/RectF;FFLandroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,rectF,rx,ry,paint);
	deleteJRectF(env,rectF);
}

//画圆角矩形
void Canvas_drawRoundRectEx(Canvas thiz,RectF rect,float rx,float ry,Paint paint)
{
	Canvas_drawRoundRect(thiz,rect.left,rect.top,rect.right,rect.buttom,rx,ry,paint);
}

//画圆
void Canvas_drawCircle(Canvas thiz,float cx,float cy,float r,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawCircel thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawCircle","(FFFLandroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,cx,cy,r,paint);
}

//画位图
void Canvas_drawBitmap(Canvas thiz,jobject bitmap,int fromLeft,int fromTop,int fromRight,int fromBottom,float toLeft,float toTop,float toRight,float toBottom,Paint paint)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_drawBitmap thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	jobject fromRect = newJRect(env,fromLeft,fromTop,fromRight,fromBottom);
	jobject toRectF   = newJRectF(env,toLeft,toTop,toRight,toBottom);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"drawBitmap","(Landroid/graphics/Bitmap;Landroid/graphics/Rect;Landroid/graphics/RectF;Landroid/graphics/Paint;)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,bitmap,fromRect,toRectF,paint);
	deleteJRect(env,fromRect);
	deleteJRectF(env,toRectF);

}

//画位图
void Canvas_drawBitmapEx(Canvas thiz,jobject bitmap,Rect rectFrom,RectF rectTo,Paint paint)
{
	Canvas_drawBitmap(thiz,bitmap,rectFrom.left,rectFrom.top,rectFrom.right,rectFrom.buttom,
			rectTo.left,rectTo.top,rectTo.right,rectTo.buttom,paint);
}

/**
 * 保存当前画布操作，
 * 以便使用Canvas_restore来恢复当前状态。
 * Canvas_save与Canvas_restore一定要配对使用！
 */
int Canvas_save(Canvas thiz)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_save thiz==NULL");
		return 0;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"save","()I");
	(*env)->DeleteLocalRef(env,clazz);
	return (*env)->CallIntMethod(env,thiz,methoID);
}

/**
 * 恢复之前保存的画布状态，
 * 与Canvas_save配对使用。
 */
void Canvas_restore(Canvas thiz)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_restore thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"restore","()V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID);
}

/**
 * 裁剪矩形，裁剪后所有的绘图操作只会在这个区域生效。
 */
void Canvas_clipRect(Canvas thiz,int left,int top,int right,int bottom)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_clipRect thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"clipRect","(IIII)Z");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallBooleanMethod(env,thiz,methoID,left,top,right,bottom);
}

/**
 * 裁剪矩形，裁剪后所有的绘图操作只会在这个区域生效。
 */
void Canvas_clipRectEx(Canvas thiz,Rect rect)
{
	Canvas_clipRect(thiz,rect.left,rect.top,rect.right,rect.buttom);
}

/**
 * 旋转画布，
 * 将画布绕着px,py旋转degress度
 */
void Canvas_rotate(Canvas thiz,float degrees,float px,float py)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_rotate thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"rotate","(FFF)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,degrees,px,py);
}

/**
 * 平移画布，
 * 将画布平移dx,dy。
 */
void Canvas_translate(Canvas thiz,float dx,float dy)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_translate thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"translate","(FF)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,dx,dy);
}

/**
 * 缩放画布
 * 将画布以px,py点为中心，横向缩放sx，纵向缩放sy。
 */
void Canvas_scale(Canvas thiz,float sx,float sy,float px,float py)
{
	if(thiz==NULL)
	{
		LOGE("Canvas_translate thiz==NULL");
		return ;
	}
	JNIEnv* env = Android_JNI_GetEnv();
	jclass clazz = getCanvasClass(env);
	static jmethodID methoID = NULL;
	if(methoID==NULL)
		methoID = (*env)->GetMethodID(env,clazz,"scale","(FFFF)V");
	(*env)->DeleteLocalRef(env,clazz);
	(*env)->CallVoidMethod(env,thiz,methoID,sx,sy,px,py);
}








